In the past month I have done nothing but code reviews and mentoring. It's forced me to work muscles I didn't know I had, but out of it has come one shining gem: a systematic method for determining test cases. Basically it's the same as the set up part of a Logic problem: figure out exactly what the code is doing (in my case, we have a written spec for each class), break it down into variables, write a truth table for all combinations (2^n rows, where n is the number of variables), and go at it. The variables can require an understanding of the code, to an extent.
For example: “Return whether there is a dependent care child or step child in A1 household” turns into: P=”There is a dependent care person who is a relative”, Q=”The relative is a child or step child”, R=”The dependent care person is in A1 household”. This may seem like white box testing, but really the code necessarily reflects the structure of business objects and these variables must reflect that as well—the objects will not change in this lifetime, so we'll call it gray box testing.
At first glance, I came up with a method to intelligently ignore certain cases rather than write all possible combinations (in this case 8, reduced to 5): test the TTT condition, and then each variation with one false (FTT, TFT, TTF), and for good measure the FFF case. This method would become more useful as the number of variables grew (t=n+2, where t is the number of tests and n is the number of variables), with 6 for 16, 7 for 32, etc. The theory was to test each variable in isolation (under the assumption that a single F would make the whole statement F):
P | Q | R |
T | T | T |
T | T | F |
T | F | T |
T | F | F |
F | T | T |
F | T | F |
F | F | T |
F | F | F |
Unfortunately that logic does not follow unless you can independently test P, Q, and R without side effects. And if that is the case, then it's futile to even test the compound combinations since you could easily prove that all outcomes would be correct!
I had to work the problem using Bayes' theorem before I really believed that the shortcut method was ineffective, because (for me, anyway) common sense would dictate that if one F were present, the whole statement would be F, and therefore testing a statement with two F`s would be moot. The problem with that line of thinking is that it is assumed that the code checking Q has no side effects on P or R. I wish the shortcut method worked!
In the end, the first part of the solution works and it's easy to develop the table of all test cases. There just isn't the shortcut that I hoped there would be. It makes me wonder if a functional language might allow a provably correct program; but more than anything, it makes me wish that I could work with a true inference engine.